﻿using MetaDemo.Forms;

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace MetaDemo
{
    class MouseHandling
    {
        static private MouseEventHandler mouseEventHandler = new MouseEventHandler(form_MouseMove);

        static Boolean handleMouseEvents = false;
        public static Boolean HandleMouseEvents { get { return handleMouseEvents; } set { handleMouseEvents = value; } }

        public static bool MouseHandlersInstalled { get { return 0 != registeredControls.Count; } }

        private static InfoButtonForm infoButtonForm = null;

        private static HashSet<Object> registeredControls = new HashSet<Object>();

        public static bool IsRegistered(Form f)
        {
            return registeredControls.Contains(f);
        }


        public static void RegisterForm(Form f)
        {
            // First make sure the buttons are ready to be displayed,
            // before installing the handlers displaying them.
            PrepareContextButtons();

            // Control already registered? Don't register a listener again.
            if (!registeredControls.Contains(f))
            {
                // Hide the control buttons, if the form is moved, resized or looses the focus.
                f.Move += new EventHandler(infoButtonForm.Locate);
                f.Resize += new EventHandler(infoButtonForm.Locate);
            }

            // Always update the mouse events, during which we possibly find new child controls.
            InstallMouseEventHandlersIfPossible(f);
        }
        private static void InstallMouseEventHandlersIfPossible(Object obj)
        {
            // Control already registered? Don't register a listener again.
            if (!registeredControls.Contains(obj))
            {
                // Install Hooks for Mouse-events on all controls.
                registeredControls.Add(obj);
                ActuallyAddEventHandler(obj);
            }

            // Install handler on child controls.
            foreach (Object child in GetChildren(obj))
            {
                InstallMouseEventHandlersIfPossible(child);
            }
        }

        private static ICollection<Object> GetChildren(Object obj)
        {
            ICollection<Object> children = new List<Object>();

            if (obj is Control) {
                Control control = (Control)obj;
                foreach (Control child in control.Controls)
                    children.Add(child);
            }

            if (obj is TabControl)
            {
                TabControl tabControl = (TabControl)obj;
                Console.WriteLine("Found TABCONTROL and adding " + tabControl.TabPages.Count + " toolstrip items.");
                foreach (TabPage page in tabControl.TabPages)
                {
                    children.Add(page);
                }
            }

            if (obj is ToolStrip)
            {
                ToolStrip toolstrip = (ToolStrip)obj;
                Console.WriteLine("Found TOOLSTRIP and adding " + toolstrip.Items.Count + " toolstrip items.");
                foreach (ToolStripItem item in toolstrip.Items)
                    children.Add(item);
            }

            if (obj is ToolStripMenuItem)
            {
                ToolStripMenuItem menuItem = (ToolStripMenuItem)obj;
                Console.WriteLine("Found TS MENU ITEM " + menuItem.Text + " and adding " + menuItem.DropDownItems.Count + " toolstrip items.");
                foreach (ToolStripItem item in menuItem.DropDownItems)
                    children.Add(item);
            }

            return children;
        }

        static void PrepareContextButtons()
        {
            if (null == infoButtonForm)
            {
                infoButtonForm = new InfoButtonForm();
            }
        }

        private static void ActuallyAddEventHandler(Object obj) {
            if (obj is Control) ((Control)obj).MouseMove += mouseEventHandler;
            else if (obj is TabPage) ((TabPage)obj).MouseMove += mouseEventHandler;
            else if (obj is ToolStripItem) ((ToolStripItem)obj).MouseMove += mouseEventHandler;
            else
            {
                throw new Exception("Cannot handle type: " + obj.GetType().Name);
            }

        }


        static void form_MouseMove(Object sender, MouseEventArgs args)
        {
            if (!handleMouseEvents || null == sender)
                return;

            Console.WriteLine("Reacting to event on: " + sender.GetType().Name);

            if (sender is Control)
            {
                infoButtonForm.Show((Control)sender);
            }
            else if (sender is ToolStripItem)
            {
                infoButtonForm.Show(((ToolStripItem)sender).Owner);
            }
            else if (sender is TabPage)
            {
                infoButtonForm.Show(((TabPage)sender).Parent);
            }
        }


    }

}